﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Web;
using System.Configuration;
using MySQL.Db;
using NLog;
using Gollie.Mail;
using Gollie.WebCache;

namespace Gollie.Payment.Targetpay
{
	public abstract class PaymentHandler
	{
		protected static Logger logger = LogManager.GetCurrentClassLogger();

		protected string transactionId = null;

		public PaymentHandler(string transactionId, bool check)
		{
			if (string.IsNullOrEmpty(transactionId))
				throw new Exception("No transactionID");

			this.transactionId = transactionId;
			logger.Debug("Transaction: {0}", transactionId);

			if (check)
			{
				if (this.IsTargetPayReferrer() == false)
				{
					throw new Exception("Referrer not from TargetPay");
				}
			}
		}

		private bool IsTargetPayReferrer()
		{
			if (Convert.ToBoolean(ConfigAppSettings.GetValue("simulatepayment")))
				return true;

			string ip = ObjectFormatter.CurrentIp;

			return ip!=null && (ip.StartsWith("89.184.168") || ip.StartsWith("78.152.58"));
		}

		protected abstract bool IsPayedConfirmed();


		public void Handle()
		{
			ResultSet resultSet = Database.Queries.GetPayment(this.transactionId);

			bool payed = false;

			if (resultSet.Count > 0)
			{
				payed = resultSet.GetBool(0, "payed");
			}
			else
			{
				throw new Exception("ERROR: Deposit transaction " + transactionId + " not found.");
			}

			if (!payed)
			{
				if (this.IsPayedConfirmed())
				{
					decimal amount = resultSet.GetDecimal(0, "amount");

					Database.Queries.SetPayed(transactionId);

					logger.Info("Payed!");
					int userid = resultSet.GetInt32(0, "userid");

					UserInfo userInfo = UserInfo.GetUserInfo(userid);

					if (userInfo == null)
					{
						logger.Error("Could not find user with id {0}, whose payment was just finalized.", userid);
						return;
					}

					resultSet = Database.Queries.GetTransactionOffers(transactionId);
					if (resultSet.Count <= 0)
					{
						logger.Error("Could not find transactions for just paid id {0}", transactionId);
						return;
					}

					DateTime now = DateTime.Now;
					Database.Queries.InsertDepositSaldoMutations(resultSet, (uint)userid, now);

					/* Save the bought deals in session, if present, so we can post the action on facebook from MyCredits.aspx */
					DataCache.Insert(Gollie.Controls.MyCredits.sessionOffersBoughtKey + "_" + userid.ToString(), resultSet, DateTime.Now.AddMinutes(10));
					//if (HttpContext.Current != null)
					//	if (HttpContext.Current.Session != null)
					//		HttpContext.Current.Session[Gollie.Controls.MyCredits.sessionOffersBoughtKey] = resultSet;

					this.SendConfirmationMail(userInfo, resultSet, amount, now);


				}
				else
				{
					logger.Info("Canceling transaction {0}", transactionId);

					Database.Queries.CancelTransaction(transactionId);

					logger.Info("Not payed!");
				}
			}
			else
			{
				logger.Debug("Already payed");
			}
		}

		private void SendConfirmationMail(UserInfo userInfo, ResultSet resultSet, decimal amount, DateTime now)
		{
			MailClient.Queue(new EMail
			{
				Name = "depositreceived",
				Recipients = userInfo.Email,
				Args = new Dictionary<string, string>()
				{
											{ "{amount}", ObjectFormatter.GetCurrencyString(amount) },
											{ "{aanhef}", userInfo.MailAanhef },
											{ "{orderbasket}", this.GetHtmlOrderBasket(resultSet, now) }
										    
				}
			});

		}

		private string GetHtmlOrderBasket(ResultSet resultSet, DateTime now)
		{
			StringBuilder str = new StringBuilder(256);

			str.Append("<style>td {padding-right: 8px; padding-left: 8px; margin: 0px; border-right: 1px solid black;} {td.right {text-align:right;} tr.head {} tr.head td {font-weight: bold; border-bottom: 1px solid black;}</style>");
			str.Append("<table>");
			str.Append("<tr class=\"head\"><td>Bedrijf</td><td class=\"right\">Aantal</td><td class=\"right\">Totaal tegoed</td><td class=\"right\">Totale prijs</td><td class=\"right\">Geldig vanaf</td><td class=\"right\">Verloopt op</td></tr>");

			for (int i = 0; i < resultSet.Count; i++)
			{
				decimal credit = resultSet.GetDecimal(i, "credit");
				decimal price = resultSet.GetDecimal(i, "price");
				uint number = resultSet.GetUInt32(i, "number");

				DateTime validFrom = resultSet.GetDateTime(i, "validfrom");
				if (validFrom < now)
					validFrom = now;

				str.Append("<tr>");

				str.Append("<td>");
				str.Append(HttpUtility.HtmlEncode(resultSet.GetString(i, "name"))); str.Append(", "); str.Append(HttpUtility.HtmlEncode(resultSet.GetString(i, "city")));
				str.Append("</td>");

				str.Append("<td class=\"right\">");
				str.Append(number);
				str.Append("</td>");

				str.Append("<td class=\"right\">");
				str.Append(ObjectFormatter.GetCurrencyString(number*credit));
				str.Append("</td>");

				str.Append("<td class=\"right\">");
				str.Append(ObjectFormatter.GetCurrencyString(number*price));
				str.Append("</td>");

				str.Append("<td class=\"right\">");
				str.Append(ObjectFormatter.GetFormattedTimeStampNoSeconds(validFrom));
				str.Append("</td>");

				str.Append("<td class=\"right\">");
				str.Append(ObjectFormatter.GetFormattedTimeStampNoSeconds(validFrom.AddHours(Convert.ToDouble(resultSet.GetUInt32(i, "expiresafter")))));
				str.Append("</td>");

				str.Append("</tr>");
			}

			str.Append("</table>");

			return str.ToString();
		}
	}
}